package com.zlm.schedule;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.locks.LockSupport;

/**
 * @author zlm
 * @date 2025/4/1
 */
public class ScheduleService {

    Trigger trigger = new Trigger();

    ExecutorService executorService = Executors.newFixedThreadPool(6);
    void schedule(Runnable task,long delay){
        Job job = new Job();
        job.setTask(task);
        job.setDelay(delay);
        job.setStartTime(System.currentTimeMillis()+delay);
        // 放入队列
        trigger.queue.offer(job);
        // 唤醒线程
        trigger.wakeUp();
    }

    /**
     * 等待合适时间，把对应的任务放到线程池中执行
     */
    class Trigger{

        //优先级队列，按照时间排序
        PriorityBlockingQueue<Job> queue = new PriorityBlockingQueue<>();

        Thread thread = new Thread(()->{
            while (true){
                //if改为while解决 线程阻塞虚假唤醒问题
                while (queue.isEmpty()){
                    //线程阻塞
                    LockSupport.park();
                }
                //
                Job ltelyJob = queue.peek();
                if(ltelyJob.getStartTime() < System.currentTimeMillis()){
                    ltelyJob = queue.poll();
                    executorService.execute(ltelyJob.getTask());
                    //计算下一个任务执行时间，放入队列中
                    Job nextJob = new Job();
                    nextJob.setTask(ltelyJob.getTask());
                    nextJob.setDelay(ltelyJob.getDelay());
                    nextJob.setStartTime(System.currentTimeMillis()+ltelyJob.getDelay());
                    queue.offer(nextJob);

                }else{
                    //线程阻塞, 直到时间到达
                    LockSupport.parkUntil(ltelyJob.getStartTime());
                }

            }
        });
        {
            thread.start();
            System.out.println("触发器启动了·········");
        }
        void wakeUp(){
            LockSupport.unpark(thread);
        }
    }
}
